#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "cmsis_os2.h"
#include "hi_i2c.h"
#include "hi_stdlib.h"
#include "hi_types_base.h"
#include "hi_i2c.h"
#include "hi_early_debug.h"
#include "hi_stdlib.h"
#include "SHT3x_I2C.h"

float Temperature_t = 0;
float Humidity_t = 0;

static void dump_buf(unsigned char * buf,unsigned int len)
{
    if(buf == NULL)
        return ;

    printf("in buf : \r\n");
    for(unsigned int i = 0; i < len; i++){
        printf("%x ",*buf++); 
    }
    printf(" \r\n");
}

static float SHT3X_CalcTemperature_t(unsigned short rawValue) 
{
    return 175.0f * (float)rawValue / 65535.0f - 45.0f; 
}

static float SHT3X_CalcHumidity_t(unsigned short rawValue) 
{
    return 100.0f * (float)rawValue / 65535.0f; 
}

static int SHT3x_WriteCMD(unsigned short cmd)
{
    int ret = -1;
    unsigned char sendbuf[2] = {0};
    unsigned char rcvbuf[2] = {0};
    
    hi_i2c_data sht3x_i2c_data = { 0 };
    sht3x_i2c_data.send_buf = sendbuf;
    sht3x_i2c_data.send_len = sizeof(sendbuf);
    sht3x_i2c_data.receive_buf = rcvbuf;
    sht3x_i2c_data.receive_len = sizeof(rcvbuf);
    
    sendbuf[0] = (cmd & 0xff00) >> 8;
    sendbuf[1] = cmd & 0xff;
    dump_buf(sendbuf,2); 
    ret = hi_i2c_write(0, ((unsigned char)0x44) << 1, &sht3x_i2c_data);
    if(ret != 0){
        printf("hi_i2c_write failed ret :%#x \r\n",ret);
        return ret;
    }
    return 0;        
}

static unsigned char SHT3X_CalcCrc(unsigned char data[], unsigned int nbrOfBytes) 
{
    unsigned char bit; // bit mask
    unsigned char crc = 0xFF; // calculated checksum
    unsigned char byteCtr; // byte counter

    // calculates 8-Bit checksum with given polynomial
    for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
    {
        crc ^= (data[byteCtr]);
        for(bit = 8; bit > 0; --bit)
        {
            if(crc & 0x80) 
                crc = (crc << 1) ^ POLYNOMIAL;
            else 
                crc = (crc << 1);
        }
    }

    return crc; 
}

static etError SHT3X_CheckCrc(unsigned char data[],\
    unsigned int nbrOfBytes, unsigned char checksum) 
{
    unsigned char crc; // calculated checksum

    // calculates 8-Bit checksum
    crc = SHT3X_CalcCrc(data, nbrOfBytes);

    // verify checksum
    if(crc != checksum) 
        return CHECKSUM_ERROR;
    else 
        return NO_ERROR; 
}

static int SHT3x_Read4BytesDataAndCrc(unsigned short *data)
{
    int ret = -1;
    unsigned char sendbuf[2] = {0};
    unsigned char rcvbuf[6] = {0};
    
    hi_i2c_data sht3x_i2c_data = { 0 };
    sht3x_i2c_data.send_buf = sendbuf;
    sht3x_i2c_data.send_len = sizeof(sendbuf);
    sht3x_i2c_data.receive_buf = rcvbuf;
    sht3x_i2c_data.receive_len = sizeof(rcvbuf);

    if(data == NULL){
        printf("invalid para \r\n");
        return ret;
    }

    ret = hi_i2c_read(0, ((unsigned char)0x44) << 1 | 0x01, &sht3x_i2c_data);
    if(ret != 0){
        printf("hi_i2c_read failed ret :%#x \r\n",ret);
        return ret;
    }
    
    ret = SHT3X_CheckCrc(rcvbuf,2,rcvbuf[2]);
    if(ret != 0){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }
    
    ret = SHT3X_CheckCrc(&rcvbuf[3],2,rcvbuf[5]);
    if(ret != 0){
        printf("read serial number crc check failed \r\n"); 
        return ret;
    }

    data[0] = rcvbuf[0] << 8 | rcvbuf[1];
    data[1] = rcvbuf[3] << 8 | rcvbuf[4];

    return 0;        
}

void SHT3X_ReadMeasurementBuffer(float* temperature, float* humidity) 
{

    unsigned int rawValueTemp = 0; 
    
    SHT3x_WriteCMD(CMD_FETCH_DATA);
    SHT3x_Read4BytesDataAndCrc((unsigned short *)&rawValueTemp);

    dump_buf((unsigned char *)&rawValueTemp,sizeof(rawValueTemp)); 

    *temperature = SHT3X_CalcTemperature_t(rawValueTemp);
    *humidity = SHT3X_CalcHumidity_t(*((unsigned short *)(&rawValueTemp)+1));
    Temperature_t = *temperature;
    Humidity_t = *humidity;
    printf("temp :%f,hum :%f \r\n",Temperature_t,Humidity_t);
}


void SHT30_Read_Data(SHT_Data_TypeDef *ReadData)
{
    float humidity = 0.0; 
    float temperature = 0.0;

    SHT3X_ReadMeasurementBuffer(&temperature,&humidity);
    ReadData->Humidity = humidity;
    ReadData->Temperature = temperature;
}

/*
    作用：SHT30初识化
*/
void SHT30_Init(void)
{
    int ret = 0;
    unsigned short data[2] = {0};
    SHT3x_WriteCMD(CMD_SOFT_RESET);
    SHT3x_WriteCMD(CMD_READ_SERIALNBR);
    
    SHT3x_WriteCMD(CMD_MEAS_PERI_2_M);
}

